#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
时间序列分析工具使用示例
版本: 1.0.0
作者: TimeSeriesIQ 开发团队
日期: 2023-11-20
描述: 演示如何使用时间序列分析工具进行数据加载、预处理、分析和可视化
"""

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from time_series_analysis import TimeSeriesDataProcessor, TimeSeriesAnalyzer
from time_series_visualization import TimeSeriesVisualizer
import warnings
warnings.filterwarnings('ignore')  # 忽略警告信息

def load_demo_data():
    """
    加载演示数据，如果没有外部数据源，则生成模拟数据
    """
    try:
        # 尝试加载真实数据集(使用pandas_datareader获取Yahoo财经数据)
        try:
            import pandas_datareader as pdr
            print("加载股票价格数据...")
            data = pdr.get_data_yahoo('AAPL', start='2020-01-01', end='2022-12-31')
            # 使用收盘价作为目标变量
            target_column = 'Close'
            print(f"成功加载股票价格数据，形状: {data.shape}")
            return data, target_column
        except Exception as e:
            print(f"加载股票数据失败: {str(e)}，将生成模拟数据...")
    
        # 如果无法获取真实数据，生成模拟时间序列数据
        np.random.seed(42)
        
        # 创建日期索引
        date_rng = pd.date_range(start='2020-01-01', end='2022-12-31', freq='D')
        n = len(date_rng)
        
        # 生成时间序列成分
        # 1. 趋势成分: 线性增长
        trend = np.linspace(0, 20, n)
        
        # 2. 季节性成分: 周期性变化
        seasonal_weekly = 5 * np.sin(2 * np.pi * np.arange(n) / 7)  # 每周的季节性
        seasonal_yearly = 10 * np.sin(2 * np.pi * np.arange(n) / 365)  # 每年的季节性
        seasonal = seasonal_weekly + seasonal_yearly
        
        # 3. 随机噪声
        noise = np.random.normal(0, 3, n)
        
        # 合并成分
        value = 100 + trend + seasonal + noise
        
        # 创建DataFrame
        data = pd.DataFrame({
            'value': value
        }, index=date_rng)
        
        # 添加一些缺失值和异常值
        # 随机选择5%的索引设为NaN
        nan_idx = np.random.choice(n, size=int(0.05 * n), replace=False)
        data.iloc[nan_idx, 0] = np.nan
        
        # 随机选择2%的索引设为异常值
        outlier_idx = np.random.choice(n, size=int(0.02 * n), replace=False)
        data.iloc[outlier_idx, 0] = data.iloc[outlier_idx, 0] * np.random.uniform(1.5, 3, len(outlier_idx))
        
        target_column = 'value'
        print(f"成功生成模拟时间序列数据，形状: {data.shape}")
        return data, target_column
        
    except Exception as e:
        print(f"加载演示数据失败: {str(e)}")
        return None, None

def run_analysis_demo():
    """
    运行时间序列分析演示
    """
    print("=" * 80)
    print("时间序列智能分析系统(TimeSeriesIQ) - 演示脚本")
    print("=" * 80)
    
    # 加载数据
    data, target_column = load_demo_data()
    if data is None:
        print("无法加载演示数据，程序退出。")
        return
    
    print("\n1. 数据基本信息:")
    print("-" * 40)
    print(data.head())
    print(f"\n数据形状: {data.shape}, 数据类型: {data.dtypes}")
    print(f"日期范围: {data.index.min()} 至 {data.index.max()}")
    print(f"缺失值数量: {data.isna().sum().sum()}")
    
    # 创建数据处理器
    dp = TimeSeriesDataProcessor()
    
    # 设置数据
    dp.data = data.copy()
    dp.target_column = target_column
    dp.time_column = data.index.name or 'date'
    
    print("\n2. 数据预处理:")
    print("-" * 40)
    
    # 处理缺失值
    print("处理缺失值...")
    dp.handle_missing_values(method='interpolate', max_gap=10)
    
    # 异常值检测和处理
    print("检测异常值...")
    outliers = dp.detect_outliers(method='iqr', threshold=1.5)
    if len(outliers) > 0:
        print(f"检测到{len(outliers)}个异常值，将进行替换...")
        dp.replace_outliers(outliers, method='interpolate')
    
    # 数据可视化
    print("\n3. 数据可视化:")
    print("-" * 40)
    visualizer = TimeSeriesVisualizer(dp)
    
    # 创建分析器
    analyzer = TimeSeriesAnalyzer(dp)
    analyzer.set_data(dp.data, dp.target_column)
    visualizer.analyzer = analyzer
    
    print("创建数据概览图...")
    fig_overview = visualizer.plot_overview()
    plt.savefig('time_series_overview.png')
    print("数据概览图已保存为 'time_series_overview.png'")
    
    print("创建季节性分析图...")
    fig_seasonality = visualizer.plot_seasonality(period=365)  # 使用365天作为年度季节性周期
    if fig_seasonality:
        plt.savefig('time_series_seasonality.png')
        print("季节性分析图已保存为 'time_series_seasonality.png'")
    
    print("创建平稳性测试图...")
    fig_stationarity = visualizer.plot_stationarity_test(window=30)
    if fig_stationarity:
        plt.savefig('time_series_stationarity.png')
        print("平稳性测试图已保存为 'time_series_stationarity.png'")
    
    print("\n4. 时间序列建模与预测:")
    print("-" * 40)
    
    # 检查平稳性
    print("检查时间序列平稳性...")
    stationarity_result = analyzer.check_stationarity()
    is_stationary = stationarity_result['adf_test']['is_stationary']
    print(f"ADF测试 p值: {stationarity_result['adf_test']['p_value']:.6f}")
    print(f"时间序列{'是' if is_stationary else '不是'}平稳的")
    
    # 如果非平稳，转换为平稳序列
    if not is_stationary:
        print("将时间序列转换为平稳序列...")
        stationary_series = analyzer.make_stationary(method='diff', order=1)
        print("已使用一阶差分转换为平稳序列")
    
    # 拟合ARIMA模型
    print("\n拟合ARIMA模型...")
    arima_model, arima_pred = analyzer.fit_arima(p=3, d=1, q=1)
    
    # 拟合LSTM模型
    print("\n拟合LSTM模型...")
    lstm_model, lstm_train_pred, lstm_test_pred = analyzer.fit_lstm(n_steps=30, epochs=30)
    
    # 可视化预测结果
    print("\n5. 预测结果可视化:")
    print("-" * 40)
    
    print("创建ARIMA预测结果图...")
    analyzer.plot_forecast_results('arima')
    plt.savefig('arima_forecast.png')
    print("ARIMA预测结果图已保存为 'arima_forecast.png'")
    
    print("创建LSTM预测结果图...")
    analyzer.plot_forecast_results('lstm')
    plt.savefig('lstm_forecast.png')
    print("LSTM预测结果图已保存为 'lstm_forecast.png'")
    
    # 检测异常
    print("\n6. 异常检测:")
    print("-" * 40)
    
    print("使用Z-score方法进行异常检测...")
    anomalies = analyzer.detect_anomalies(method='zscore', threshold=3)
    
    if len(anomalies) > 0:
        print(f"检测到{len(anomalies)}个异常点")
        print("创建异常检测结果图...")
        analyzer.plot_anomalies(anomalies)
        plt.savefig('anomaly_detection.png')
        print("异常检测结果图已保存为 'anomaly_detection.png'")
    else:
        print("未检测到异常点")
    
    # 模型比较
    print("\n7. 模型性能比较:")
    print("-" * 40)
    
    metrics_df = analyzer.evaluate_models()
    print("\n模型性能指标:")
    print(metrics_df)
    
    plt.savefig('model_comparison.png')
    print("模型比较图已保存为 'model_comparison.png'")
    
    print("\n8. 交互式仪表盘:")
    print("-" * 40)
    print("要启动交互式仪表盘，请取消以下代码的注释:")
    print("visualizer.run_dashboard()")
    
    # 启动交互式仪表盘
    visualizer.run_dashboard()
    
    print("\n" + "=" * 80)
    print("演示完成! 所有图表已保存到当前目录。")
    print("=" * 80)

if __name__ == "__main__":
    run_analysis_demo()
